package com.shycloud.mido.common.pay.wxpay;

import cn.hutool.core.map.MapUtil;
import com.shycloud.mido.common.pay.wxpay.utils.PayCommonUtil;
import com.shycloud.mido.common.pay.wxpay.utils.WxConfigUtil;
import com.shycloud.mido.common.pay.wxpay.utils.XMLUtil;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.JDOMException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;

/**
 * 微信支付接口
 *
 * @author nianhua.jiang
 * @date 2020/7/8 13:41
 */
@UtilityClass
@Slf4j
public class WXPay {

	private static Log logger = LogFactory.getLog(WXPay.class);

	private static final String UTF = "UTF-8";

	private static final String SUCCESS = "SUCCESS";

	private static final String RESULT_CODE = "result_code";

	/**
	 * 微信支付
	 *
	 * @param price      总金额
	 * @param body       商品描述
	 * @param notifyUrl  回调地址
	 * @param outTradeNo 订单号
	 * @return R
	 */
	public static Map<String, Map> wxPrePay(String appId, String price, String body, String notifyUrl, String outTradeNo,
			HttpServletRequest request) {

		/**创建结果集*/
		Map<String, Map> resultMap = MapUtil.newHashMap();

		Map<String, Object> flag = new TreeMap<>();

		SortedMap<Object, Object> parameters = new TreeMap<>();

		//调用创建统一下单签名
		parameters = PayCommonUtil.createUnifiedSign(appId, price, body, notifyUrl, outTradeNo, request);

		//封装请求参数结束
		String requestXML = PayCommonUtil.getRequestXml(parameters);

		//调用统一下单接口
		String result = PayCommonUtil.httpsRequest(WxConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML);
		System.out.println("\n" + result);
		try {

			/**
			 * 统一下单接口返回正常的 prepay_id，再按签名规范重新生成签名后，将数据传输给 APP。
			 * 参与签名的字段名为 appId，partnerId，prepayId，nonceStr，timeStamp，package。
			 * 注意：package 的值格式为 Sign = WXPayNative
			 **/
			Map<String, String> map = XMLUtil.doXMLParse(result);
			SortedMap<Object, Object> parameterMap2 = new TreeMap<Object, Object>();
			parameterMap2.put("appid", appId);
			parameterMap2.put("partnerid", WxConfigUtil.MCH_ID);
			parameterMap2.put("prepayid", map.get("prepay_id"));
			parameterMap2.put("package", "Sign=WXPay");
			parameterMap2.put("noncestr", PayCommonUtil.createNoncestr());
			//本来生成的时间戳是13位，但是ios必须是10位，所以截取了一下
			parameterMap2.put("timestamp", Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0, 10)));
			String sign2 = PayCommonUtil.createSign("UTF-8", parameterMap2);
			parameterMap2.put("sign", sign2);
			parameterMap2.put("out_trade_no", outTradeNo);
			flag.put("flag", true);
			resultMap.put("flag", flag);
			resultMap.put("wxPay", parameterMap2);
			return resultMap;
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return resultMap;
	}

	public static Map<String, Map> miniPrePay(String appId, String price, String body, String openId, String notifyUrl,
			String outTradeNo,
			HttpServletRequest request) {

		/**创建结果集*/
		Map<String, Map> resultMap = MapUtil.newHashMap();

		Map<String, Object> flag = new TreeMap<>();

		SortedMap<Object, Object> parameters = new TreeMap<>();

		//调用创建统一下单签名
		parameters = PayCommonUtil.createMiniUnifiedSign(appId, price, body, openId, notifyUrl, outTradeNo, request);

		//封装请求参数结束
		String requestXML = PayCommonUtil.getRequestXml(parameters);
		//调用统一下单接口
		String result = PayCommonUtil.httpsRequest(WxConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML);
		System.out.println("\n" + result);
		try {

			/**
			 * 统一下单接口返回正常的 prepay_id，再按签名规范重新生成签名后，将数据传输给 APP。
			 * 参与签名的字段名为 appId，partnerId，prepayId，nonceStr，timeStamp，package。
			 * 注意：package 的值格式为 Sign = WXPayNative
			 **/
			Map<String, String> map = XMLUtil.doXMLParse(result);
			SortedMap<Object, Object> parameterMap2 = new TreeMap<Object, Object>();
			parameterMap2.put("appId", appId);
			parameterMap2.put("nonceStr", map.get("nonce_str"));
			parameterMap2.put("package", "prepay_id=" + map.get("prepay_id"));
			parameterMap2.put("signType", "MD5");
			parameterMap2.put("timeStamp", Long.parseLong(String.valueOf(System.currentTimeMillis()).toString()));

			String sign2 = PayCommonUtil.createSign("UTF-8", parameterMap2);
			parameterMap2.put("sign", sign2);
			parameterMap2.put("out_trade_no", outTradeNo);
			flag.put("flag", true);
			resultMap.put("flag", flag);
			resultMap.put("wxPay", parameterMap2);
			return resultMap;
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return resultMap;
	}

	/**
	 * 微信支付
	 *
	 * @return R
	 */
	public static Map<String, String> wxNotify(HttpServletRequest request, HttpServletResponse response)
			throws IOException, JDOMException {
		//读取参数
		boolean flag = false;
		InputStream inputStream;
		StringBuffer sb = new StringBuffer();
		inputStream = request.getInputStream();
		String s;
		BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
		while ((s = in.readLine()) != null) {
			sb.append(s);
		}
		in.close();
		inputStream.close();
		//解析 xml 成 map
		Map<String, String> m = new HashMap<String, String>();
		m = XMLUtil.doXMLParse(sb.toString());
		log.info("微信回调参数如下");
		for (Object keyValue : m.keySet()) {
			log.info(keyValue + "=" + m.get(keyValue));
		}
		return m;
	}

	/**
	 * 微信支付
	 *
	 * @return R
	 */
	public static boolean wxNotify(Map<String, String> m, String payStatus, HttpServletRequest request, HttpServletResponse response)
			throws IOException, JDOMException {
		boolean flag = false;
		//过滤空 设置 TreeMap
		SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
		Iterator it = m.keySet().iterator();
		while (it.hasNext()) {
			String parameter = (String) it.next();
			String parameterValue = m.get(parameter);
			String v = "";
			if (null != parameterValue) {
				v = parameterValue.trim();
			}
			packageParams.put(parameter, v);
		}
		//判断签名是否正确
		String resXml = "";
		if (PayCommonUtil.isTenpaySign(UTF, packageParams)) {
			if (SUCCESS.equals((String) packageParams.get(RESULT_CODE))) {
				resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
				logger.info("订单已处理");
				flag = true;
				return flag;
			}
		}

//        if (PayCommonUtil.isTenpaySign("UTF-8", packageParams)) {
//            if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
//                // 这里是支付成功
//                //商户号
//                String mchId = (String) packageParams.get("mch_id");
//                //用户标识
//                String openId = (String) packageParams.get("openid");
//                //商户订单号
//                String outTradeNo = (String) packageParams.get("out_trade_no");
//                String totalFee = (String) packageParams.get("total_fee");
//                //微信支付订单
//                String transactionId = (String) packageParams.get("transaction_id");
//                if (!WxConfigUtil.MCH_ID.equals(mchId) ||  new BigDecimal(totalFee).compareTo(new BigDecimal(price).multiply(new BigDecimal(100))) != 0) {
//                    logger.info("支付失败,错误信息：" + "参数错误");
//                    resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
//                            + "<return_msg><![CDATA[参数错误]]></return_msg>" + "</xml> ";
//                } else {
//                    if ("0".equals(payStatus)) {
//                        //支付的价格
//                        //订单状态的修改。根据实际业务逻辑执行
//                        resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
//                                + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
//                        flag = true;
//                        return flag;
//
//                    } else {
//                        resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
//                                + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
//                        logger.info("订单已处理");
//                        flag = true;
//                        return flag;
//                    }
//                }
//            } else {
//                logger.info("支付失败,错误信息：" + packageParams.get("err_code"));
//                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
//                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
//                return flag;
//            }
//
//
//        } else {
//            resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
//                    + "<return_msg><![CDATA[通知签名验证失败]]></return_msg>" + "</xml> ";
//            logger.info("通知签名验证失败");
//            return flag;
//        }
		//------------------------------
		//处理业务完毕
		//------------------------------
//		BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
//		out.write(resXml.getBytes());
//		out.flush();
//		out.close();
		return flag;
	}

//    /**
//     * 微信退款
//     * @param rdfund
//     * @param req
//     * @return
//     * @throws Exception
//     */
//    public static Map<String, Object>  refundUtil(RefundModel rdfund, HttpServletRequest req,Integer type) throws Exception{
//        Map<String, Object> map = new HashMap<String, Object>();
//        int price100 = new BigDecimal(rdfund.getRefund_fee()).multiply(new BigDecimal(100)).intValue();
//        if (price100 <= 0) {
//            logger.error("微信退款失败》》"+"错误码:"+map.get("return_msg")+"  ;"
//                    + "描述:"+map.get("err_code_des"));
//            return map;
//        }

//        Map<String, Object> mp = new HashMap<String, Object>();
//        //设置支付账户信息
//        String MchKey = ""; //商户号秘钥
//        String MchId = ""; //商户号id
//        rdfund.setAppid(BasicInfo.APP_AppID);
//        rdfund.setMch_id(BasicInfo.APP_MchId);
//        MchKey = BasicInfo.APP_MchKey;
//        MchId = BasicInfo.APP_MchId;
//
//
//        rdfund.setNonce_str(PayUtil.getRandomStr());
//        rdfund.setSign_type("MD5");
//        rdfund.setSign(SignUtil.sign(SignUtil.createRefundSign(rdfund),MchKey));
//
//        try{
//            XMLUtil xmlUtil= new XMLUtil();
//            xmlUtil.xstream().alias("xml", rdfund.getClass());
//
//            String xml = xmlUtil.xstream().toXML(rdfund);
//            String response = PayUtil.ssl(BasicInfo.refundurl, xml,req,MchId);
//            System.out.println(response);
//            Map<String, String> map = xmlUtil.parseXml(response);
//            if("SUCCESS".equals(map.get("result_code"))){
//                mp.put("stu", true);
//                return mp;
//            }else{
//                mp.put("stu", false);
//                mp.put("errMsg", map.get("return_msg"));
//                mp.put("errDes", map.get("err_code_des"));
//                log.error("微信退款失败》》"+"错误码:"+map.get("return_msg")+"  ;"
//                        + "描述:"+map.get("err_code_des"));
//                return mp;
//            }
//        }catch (Exception e) {
//            log.error("微信退款异常》》"+e);
////            throw new MyException(SystemError.WX_RETREIEV_ERROR.getCode(),
////                    SystemError.WX_RETREIEV_ERROR.getMessage());
////        }
//        return map;
//    }

	public static Map<String, Map> contractorder(String appId, String price, String body, String notifyUrl, String outTradeNo,
			HttpServletRequest request) {

		//
		Map<String, Map> resultMap = MapUtil.newHashMap();

		Map<String, Object> flag = new TreeMap<>();

		SortedMap<Object, Object> parameters = new TreeMap<>();

		//调用创建统一下单签名
		parameters = PayCommonUtil.createUnifiedSign(appId, price, body, notifyUrl, outTradeNo, request);

		//封装请求参数结束
		String requestXML = PayCommonUtil.getRequestXml(parameters);

		//调用委托代扣接口
		String result = PayCommonUtil.httpsRequest(WxConfigUtil.CONTRACT_ORDER_URL, "POST", requestXML);
		System.out.println("\n" + result);

		try {

			/**
			 * 统一下单接口返回正常的 prepay_id，再按签名规范重新生成签名后，将数据传输给 APP。
			 * 参与签名的字段名为 appId，partnerId，prepayId，nonceStr，timeStamp，package。
			 * 注意：package 的值格式为 Sign = WXPayNative
			 **/
			Map<String, String> map = XMLUtil.doXMLParse(result);
			SortedMap<Object, Object> parameterMap2 = new TreeMap<Object, Object>();
			parameterMap2.put("appid", appId);
			parameterMap2.put("partnerid", WxConfigUtil.MCH_ID);
			parameterMap2.put("prepayid", map.get("prepay_id"));
			parameterMap2.put("package", "Sign=WXPay");
			parameterMap2.put("noncestr", PayCommonUtil.createNoncestr());
			//本来生成的时间戳是13位，但是ios必须是10位，所以截取了一下
			parameterMap2.put("timestamp", Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0, 10)));
			String sign2 = PayCommonUtil.createSign("UTF-8", parameterMap2);
			parameterMap2.put("sign", sign2);
			parameterMap2.put("out_trade_no", outTradeNo);
			flag.put("flag", true);
			resultMap.put("flag", flag);
			resultMap.put("wxPay", parameterMap2);
			return resultMap;

		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return resultMap;
	}

}


